# import sys
# sys.path.append('../../..')

import yaml
from src.app import app
from typing import Dict,List
from src.scheme.scheme import SchemeManager, schemes_dict
from flask import Response
import time
from src.grpc.clients.image_render.image_render_client import ImageRenderClient

image_render_clients_dict : Dict[int, ImageRenderClient] = {}

@app.route('/scheme/start/<int:task_id>')
def scheme_start(task_id: int):
    scheme = None
    try:
        if task_id in schemes_dict:
            raise RuntimeError('task already exists.')
        scheme_file = f'schemes/{task_id}.yml'
        scheme = SchemeManager(scheme_file)
        schemes_dict[task_id] = scheme
        scheme.connect()
        video_render_address = scheme.service_address['image render']
        image_render_clients_dict[task_id] = ImageRenderClient(video_render_address[0], video_render_address[1])
        return 'OK'
        # return True
    except Exception as e:
        error = '\n'.join([
            f'start task {task_id} error:',
            str(e)
        ])
        try:
            if scheme is not None:
                scheme.stop()
        except Exception as e:
            error = '\n'.join([
                error,
                f'stop task {task_id} error:',
                str(e)
            ])
        if task_id in schemes_dict:
            schemes_dict.pop(task_id)
        return Response(f"<pre>{error}</pre>", mimetype='text/html')
        # return False

@app.route('/scheme/check/<int:task_id>')
def scheme_check(task_id: int):
    if task_id in schemes_dict:
        return 'OK'
    return 'No'

@app.route('/scheme/stop/<int:task_id>')
def scheme_stop(task_id: int):
    try:
        scheme = schemes_dict[task_id]
        scheme.stop()
        if task_id in image_render_clients_dict:
            image_render_clients_dict.pop(task_id)
        if task_id in schemes_dict:
            schemes_dict.pop(task_id)
        return 'OK'
    except Exception as e:
        error = '\n'.join([
            f'stop task {task_id} error:',
            str(e)
        ])
        return Response(f"<pre>{error}</pre>", mimetype='text/html')

def video_play(task_id: int):
    previous_image_id = None  # 初始化前一个image_id为None
    last_change_time = time.time()  # 记录最近一次image_id改变的时间

    while True:
        assert task_id in image_render_clients_dict, f"task id {task_id} not found"
        image_id, buffer = image_render_clients_dict[task_id].get_image_buffer_by_image_id(task_id, 0, 640, 360)

        if image_id == 0:
            continue

        # 如果image_id改变了，更新previous_image_id，重置last_change_time为当前时间
        if image_id != previous_image_id:
            previous_image_id = image_id
            last_change_time = time.time()
        else:
            # 如果image_id没有改变，并且自上次变化已经超过1秒，则结束循环
            if time.time() - last_change_time > 1:
                break

        if not buffer:
            continue

        # 使用生成器（generator）输出图像帧
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + buffer + b'\r\n')

    scheme_stop(task_id)



@app.route('/scheme/video/<int:task_id>')
def video_feed(task_id: int):
    return Response(video_play(task_id),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

# 使用dict.fromkeys()保持顺序地去重
def remove_duplicates(lst):
    return list(dict.fromkeys(lst))

camera_list:List[str]=['192.168.1.16',
                       '192.168.1.10',
                       '192.168.1.8',
                       '192.168.1.4',
                       '192.168.1.5',
                       '192.168.1.12',
                       '192.168.1.177']

camera_dict:Dict[str,str]={
    '0':'192.168.1.16',
    '1':'192.168.1.10',
    '2':'192.168.1.8',
    '3':'192.168.1.4',
    '4':'192.168.1.5',
    '5':'192.168.1.12',
    '6':'192.168.1.177'
}
CAMERA_NUM=7 #0..6

algorithm_list:List[str]=['target detection',
                          'target tracking',
                          'behavior recognition']
ALGORITHM_NUM=3 #0,1,2

def change_camera_list(jsonFile):
    method=jsonFile['method']
    camera=jsonFile['cameara']
    global CAMERA_NUM
    #去重
    camera_list=remove_duplicates(camera_list)
    if method=='add' and camera not in camera_list:
        camera_list.append(camera)
    elif method=='delete'and camera in camera_list:
        camera_list.remove(camera)
    CAMERA_NUM=len(camera_list)

def change_algorithm_list(jsonFile):
    method=jsonFile['method']
    algorithm=jsonFile['algorithm']
    global ALGORITHM_NUM
    #去重
    algorithm_list=remove_duplicates(algorithm_list)
    if method=='add' and algorithm not in algorithm_list:
        camera_list.append(algorithm)
    elif method=='delete'and algorithm in algorithm_list:
        camera_list.remove(algorithm)
    ALGORITHM_NUM=len(algorithm_list)

def get_unique_int(num1:int,num2:int):
    return num1*(max(num1,num2)+1)+num2

def task_json2yml(jsonFile):
    taskId=jsonFile['taskId']
    cameraId=jsonFile['cameraId']
    taskId_num=int(taskId)
    cameraId_num=int(cameraId)
    unique_id=get_unique_int(taskId_num,cameraId_num)

    if taskId_num < ALGORITHM_NUM and cameraId_num < CAMERA_NUM:
        with open('/workspace/schemes/original/'+taskId+'.yml','r') as f:
            yaml_data=yaml.safe_load(f)
            yaml_data['modules']['image harmony gRPC']['input args']['DeviceAddress']=camera_dict[cameraId]
        with open('/workspace/schemes/'+str(unique_id)+'.yml','w') as f:
            yaml.safe_dump(yaml_data,f)
    return unique_id